package com.dd.cloud.common.utils;

import com.dd.cloud.common.constants.FileConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.net.URLDecoder;
import java.text.DecimalFormat;

@Slf4j
public class FileUtil {
    //文件上传限制大小
    private final static Integer FILE_SIZE = 5;
    //文件上传限制单位（B,K,M,G）
    private final static String FILE_UNIT = "M";

    public static void rename(String path) {
        File dir = new File(path);
        File[] files = dir.listFiles();

        //遍历文件数组
        for (File file : files) {
            String fileName = file.getName();
            //是否是文件
            if (file.isFile()) {
                //是否包含需要删除的字符串
                int i;
                if ((i = fileName.indexOf("Zk")) != -1) {
                    //更改文件名
                    String newName = file.getParent() + File.separator +
                            fileName.substring(0, i) + fileName.substring(i + "Zk".length());
                    System.out.println("newName=" + newName);
                    file.renameTo(new File(newName));
                }
                //是否是文件夹
            } else if (file.isDirectory()) {
                //对当前文件夹进行迭代
                rename(file.getAbsolutePath());
            }
        }
    }


    /**
     * 2      * 通过文件路径直接修改文件名
     * 3      *
     * 4      * @param filePath    需要修改的文件的完整路径
     * 5      * @param newFileName 需要修改的文件的名称
     * 6      * @return
     * 7
     */
    public static String FixFileName(String filePath, String newFileName) {
        File f = new File(filePath);
        if (!f.exists()) { // 判断原文件是否存在（防止文件名冲突）
            return null;
        }
        newFileName = newFileName.trim();
        if ("".equals(newFileName) || newFileName == null) // 文件名不能为空
            return null;
        String newFilePath = null;
        if (f.isDirectory()) { // 判断是否为文件夹
            newFilePath = filePath.substring(0, filePath.lastIndexOf("/")) + "/" + newFileName;
        } else {
            newFilePath = filePath.substring(0, filePath.lastIndexOf("/")) + "/" + newFileName
                    + filePath.substring(filePath.lastIndexOf("."));
        }
        File nf = new File(newFilePath);
        try {
            f.renameTo(nf); // 修改文件名
        } catch (Exception err) {
            err.printStackTrace();
            return null;
        }
        return newFilePath;
    }

    /**
     * 将文件大小由直接转换为可读单位
     *
     * @param size
     * @return
     */
    public static String readableFileSize(long size) {
        if (size <= 0) {
            return "0";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    /**
     * 验证文件大小
     *
     * @param len  文件长度
     * @param size 限制大小
     * @param unit 限制单位（B,K,M,G）
     * @描述 判断文件大小
     */
    public static boolean checkFileSize(Long len, int size, String unit) {
        double fileSize = 0;
        if (FileConstants.SizeUnit.B.equalsIgnoreCase(unit)) {
            fileSize = (double) len;
        } else if (FileConstants.SizeUnit.KB.equalsIgnoreCase(unit)) {
            fileSize = (double) len / 1024;
        } else if (FileConstants.SizeUnit.MB.equalsIgnoreCase(unit)) {
            fileSize = (double) len / 1048576;
        } else if (FileConstants.SizeUnit.GB.equalsIgnoreCase(unit)) {
            fileSize = (double) len / 1073741824;
        }
        return !(fileSize > size);
    }

    /**
     * 输入流获取封装得MultipartFile
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return MultipartFile
     */
    public static MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
        FileItem fileItem = createFileItem(inputStream, fileName);
        //CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
        return new CommonsMultipartFile(fileItem);
    }


    /**
     * FileItem类对象创建
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return FileItem
     */
    public static FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[10 * 1024 * 1024];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {
            log.error("Stream copy exception", e);
            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);

                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);
                }
            }
        }
        return item;
    }


    /**
     * 根据下载地址url获取文件名称
     *
     * @param url
     * @throws IOException
     */
    public static String getFilenameByUrl(String url) {
        String fileName = null;
        try {
            //url编码处理，中文名称会变成百分号编码
            String decode = URLDecoder.decode(url, "utf-8");
            fileName = decode.substring(decode.lastIndexOf("/") + 1);
            log.info("fileName :" + fileName);
        } catch (UnsupportedEncodingException e) {
            log.error("getFilenameByUrl() called with exception => 【url = {}】", url, e);
            e.printStackTrace();
        }
        return fileName;
    }

    public static File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();

        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若须要防止生成的临时文件重复,能够在文件名后添加随机码
        String nameNotPrefix = getFileNameNotPrefix(fileName);
        //避免Prefix string too short 异常, 文件名要大于等于3
        if (nameNotPrefix != null && nameNotPrefix.length() < 3) {
            nameNotPrefix = nameNotPrefix + "-1";
        }
        try {
            File file = File.createTempFile(nameNotPrefix, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取文件名不带后缀
     *
     * @param fileName
     * @return
     */
    public static String getFileNameNotPrefix(String fileName) {
        String prefix = fileName.substring(fileName.indexOf("."));
        //得到后缀名长度
        int num = prefix.length();
        //得到文件名。去掉了后缀
        String fileOtherName = fileName.substring(0, fileName.length() - num);
        return fileOtherName;
    }

    /**
     * 将MultipartFile 图片文件编码为base64
     *
     * @param file
     * @param status true加:data:multipart/form-data;base64,前缀   false 不加前缀
     * @return
     */
    public static String generateBase64(MultipartFile file, Boolean status) {
        if (file == null || file.isEmpty()) {
            throw new RuntimeException("图片不能为空！");
        }
        String fileName = file.getOriginalFilename();
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        String contentType = file.getContentType();
        byte[] imageBytes = null;
        String base64EncoderImg = "";
        try {
            imageBytes = file.getBytes();
            BASE64Encoder base64Encoder = new BASE64Encoder();
            /**
             * 1.Java使用BASE64Encoder 需要添加图片头（"data:" + contentType + ";base64,"），
             *   其中contentType是文件的内容格式。
             * 2.Java中在使用BASE64Enconder().encode()会出现字符串换行问题，这是因为RFC 822中规定，
             *   每72个字符中加一个换行符号，这样会造成在使用base64字符串时出现问题，
             *   所以我们在使用时要先用replaceAll("[\\s*\t\n\r]", "")解决换行的问题。
             */
            if (status) {
                base64EncoderImg = "data:" + contentType + ";base64," + base64Encoder.encode(imageBytes);
            } else {
                base64EncoderImg = base64Encoder.encode(imageBytes);
            }
            base64EncoderImg = base64EncoderImg.replaceAll("[\\s*\t\n\r]", "");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return base64EncoderImg;
    }
}
